package cn.hgy.infrastructure.adapter.reponsiroty;

import cn.hgy.domain.tag.model.entity.CrowdTagsJobEntity;
import cn.hgy.domain.tag.repository.ITagRepository;
import cn.hgy.infrastructure.dao.ICrowdTagsDao;
import cn.hgy.infrastructure.dao.ICrowdTagsDetailDao;
import cn.hgy.infrastructure.dao.ICrowdTagsJobDao;
import cn.hgy.infrastructure.dao.po.CrowdTags;
import cn.hgy.infrastructure.dao.po.CrowdTagsDetail;
import cn.hgy.infrastructure.dao.po.CrowdTagsJob;
import cn.hgy.infrastructure.redis.IRedisService;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RBitSet;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;

/**
 * 人群标签数据访问仓储
 * 职责：封装人群标签相关的数据操作逻辑，协调数据库与Redis缓存
 * 主要功能：
 *   1. 查询标签计算任务配置
 *   2. 添加用户ID到标签人群
 *   3. 更新标签统计人数
 */
@Repository
@RequiredArgsConstructor
public class TagRepository implements ITagRepository {

    private final ICrowdTagsDao crowdTagsDao;
    private final ICrowdTagsDetailDao crowdTagsDetailDao;
    private final ICrowdTagsJobDao crowdTagsJobDao;

    private final IRedisService redisService;

    /**
     * 查询人群标签计算任务配置实体
     *
     * @param tagId  标签ID
     * @param batchId 计算批次ID
     * @return 标签任务配置实体（包含计算规则和时间范围）
     */
    @Override
    public CrowdTagsJobEntity queryCrowdTagsJobEntity(String tagId, String batchId) {
        CrowdTagsJob crowdTagsJobReq = new CrowdTagsJob();
        crowdTagsJobReq.setTagId(tagId);
        crowdTagsJobReq.setBatchId(batchId);

        CrowdTagsJob crowdTagsJobRes = crowdTagsJobDao.queryCrowdTagsJob(crowdTagsJobReq);
        if (null == crowdTagsJobRes) return null;

        // 将Dao实体转化为领域实体
        return CrowdTagsJobEntity.builder()
                .tagType(crowdTagsJobRes.getTagType())
                .tagRule(crowdTagsJobRes.getTagRule())
                .statStartTime(crowdTagsJobRes.getStatStartTime())
                .statEndTime(crowdTagsJobRes.getStatEndTime())
                .build();
    }

    /**
     * 添加用户到标签人群
     * 双写策略：同时写入数据库和Redis位图
     *
     * @param tagId  标签ID
     * @param userId 用户ID
     */
    @Override
    public void addCrowdTagsUserId(String tagId, String userId) {
        CrowdTagsDetail crowdTagsDetailReq = new CrowdTagsDetail();
        crowdTagsDetailReq.setTagId(tagId);
        crowdTagsDetailReq.setUserId(userId);

        try {
            // 写入数据库 TODO 会有主键冲突
            crowdTagsDetailDao.addCrowdTagsUserId(crowdTagsDetailReq);

            // 2. 更新Redis位图
            // 获取标签对应的位图
            RBitSet bitSet = redisService.getBitSet(tagId);
            bitSet.set(redisService.getIndexFromUserId(userId), true);
        } catch (DuplicateKeyException ignore) {
            // 忽略唯一索引冲突
        }
    }

    /**
     * 更新标签人群统计数量
     * @param tagId
     * @param count
     */
    @Override
    public void updateCrowdTagsStatistics(String tagId, int count) {
        CrowdTags crowdTagsReq = new CrowdTags();
        crowdTagsReq.setTagId(tagId);
        crowdTagsReq.setStatistics(count);

        crowdTagsDao.updateCrowdTagsStatistics(crowdTagsReq);
    }
}
